package com.suning.sawp.service.impl.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.suning.framework.dal.client.DalClient;
import com.suning.framework.image.service.ImageServiceClient;
import com.suning.framework.image.service.ImageServiceClientImpl;
import com.suning.framework.image.service.ImageServiceException;
import com.suning.sawp.constants.ConfigConstants;
import com.suning.sawp.constants.ExportConstants;
import com.suning.sawp.dto.common.EmployeeInfo;
import com.suning.sawp.dto.common.OrgInfo;
import com.suning.sawp.dto.model.ModelAnalyseInDto;
import com.suning.sawp.dto.model.ModelSaleTopInDto;
import com.suning.sawp.intf.model.ModelAnalyseInService;
import com.suning.sawp.intf.model.ModelConstant;
import com.suning.sawp.intf.model.dto.ModelAreaRecommendDto;
import com.suning.sawp.intf.model.dto.ModelCompanyRecommendDto;
import com.suning.sawp.intf.model.vo.ModelRecommendBaseVo;
import com.suning.sawp.service.util.CsvUtils;
import com.suning.sawp.service.util.DJStringUtils;
import com.suning.sawp.service.util.DateUtils;
import com.suning.sawp.service.util.ExportFileUtil;
import com.suning.sawp.service.util.SCMConfigUtil;
import com.suning.sawp.vo.csv.ExportCsvFileVo;
import com.suning.sawp.vo.model.ModelContributionAreaExResponse;
import com.suning.sawp.vo.model.ModelContributionAreaResponse;
import com.suning.sawp.vo.model.ModelContributionInAreaVo;
import com.suning.sawp.vo.model.ModelContributionInVo;
import com.suning.sawp.vo.model.ModelContributionMonthVo;
import com.suning.sawp.vo.model.ModelContributionResponse;
import com.suning.sawp.vo.model.ModelSaleTopInVo;
import com.suning.sawp.vo.model.ModelSaleTopResponse;
import com.suning.sawp.vo.model.ModelValidAreaResponse;
import com.suning.sawp.vo.model.ModelValidAreaVo;
import com.suning.sawp.vo.model.ModelValidInAreaResponse;
import com.suning.sawp.vo.model.ModelValidInAreaVo;
import com.suning.sawp.vo.model.ModelValidMonthVo;
import com.suning.sawp.vo.model.ModelValidResponse;

/**
 * 后台样机分析服务
 * 
 * @author 15050519
 * @see [相关类/方法]（可选）
 * @since [产品/模块版本] （可选）
 */
@Service("modelAnalyseInService")
public class ModelAnalyseInServiceImpl implements ModelAnalyseInService {

    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ModelAnalyseInServiceImpl.class);

    // 计算循环次数
    private static final int loopSize = 1000;
    /**
     * 比率默认值
     */
    private static final String RATE_DEFAULT = "0.0";
    
    /**
     * 数量默认值
     */
    private static final String NUM_DEFAULT = "0";
    
    /**
     * 比率
     */
    private static final String RATE_FLAG = "%";
    
    /**
     * 数据库操作对象
     */
    @Resource
    DalClient dalClient;
    
    @Resource
    ExportFileUtil exportFileUtil;

    /**
     * 查询全国样机有效率
     * 
     * @param cateCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Override
    public ModelValidResponse queryModelValid(String region5Code, String cateCode) {
        LOGGER.info("queryModelValid enter, region5Code={},cateCode={}", region5Code, cateCode);
        ModelValidResponse resp = new ModelValidResponse();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        // 品类不为空时
        if (StringUtils.isNotBlank(cateCode)) {
            queryMap.put("cateCode", cateCode);
        }
        // 大区编码不为空时
        if (StringUtils.isNotBlank(region5Code)) {
            queryMap.put("disCode", region5Code);
        }
        // 取前12个月数据(包含当前月)
        List<String> months = getTwelveMonths();
        queryMap.put("months", months);
        // 查询库数据
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_VALID", queryMap,
                ModelAnalyseInDto.class);
        // 设置结果数据
        resp.setList(convertModelValid(months, models));
        LOGGER.info("queryModelValid exit, cateCode={}", cateCode);
        return resp;
    }

    /**
     * 获取12个月月份 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private static List<String> getTwelveMonths() {
        List<String> months = new ArrayList<String>();
        // 12月
        for (int i = 11; i >= 0; i--) {
            // 由远及进
            months.add(DateUtils.getMonth(-i));
        }
        return months;
    }

    /**
     * 查询大区或者分公司样机有效率
     * 
     * @param disCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Override
    public ModelValidInAreaResponse queryModelValidArea(String disCode, String belongDisCode, int currIndex, int size) {
        LOGGER.info("queryModelValidArea enter, disCode={}, belongDisCode={}", disCode, belongDisCode);
        ModelValidInAreaResponse resp = new ModelValidInAreaResponse();
        List<ModelValidInAreaVo> list = new ArrayList<ModelValidInAreaVo>();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        // 大区编码不为空时
        if (StringUtils.isNotBlank(disCode)) {
            queryMap.put("disCode", disCode);
        } else {
            if (StringUtils.isNotBlank(belongDisCode)) {
                queryMap.put("belongDisCode", belongDisCode);
            }
        }
        
        queryMap.put("currIndex", currIndex);
        queryMap.put("size", size);
        // 取前12个月数据(包含当前月)
        List<String> months = getTwelveMonths();
        queryMap.put("months", months);
        
        Integer total = dalClient.queryForObject("MODEL_ANALYSE_IN.QUERY_MODEL_VALID_AREA_TOTAL", queryMap,
                Integer.class);
        // 设置总记录数
        resp.setTotalSize(null != total ? total : 0);

        // 查询出分页数据,大区集合or分公司集合
        List<String> codes = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_VALID_AREA_PAGE", queryMap,
                String.class);
        // 没有分页数据，直接返回
        if (CollectionUtils.isEmpty(codes)) {
            resp.setList(list);
            return resp;
        }
        // 存在大区编码时,查询的是分公司下的数据
        if (StringUtils.isNotBlank(disCode)) {
            queryMap.put("disCode", disCode);
            queryMap.put("branchCodes", codes);
        } else {
            queryMap.put("disCodes", codes);
        }
        
        // 查询库数据
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_VALID_AREA", queryMap,
                ModelAnalyseInDto.class);
        
        // 记录数不为空时
        if (CollectionUtils.isNotEmpty(models)) {
            // 按照大区或分公司编码,组装对应12个月的数据集合MAP
            Map<String, List<ModelAnalyseInDto>> modelMap = new HashMap<String, List<ModelAnalyseInDto>>();
            List<ModelAnalyseInDto> temp;
            ModelValidInAreaVo areaVo;
            String areaCode;
            // 组装MAP集合
            for (ModelAnalyseInDto dto : models) {
                // 根据传参大区编码,判断取分公司编码,还是大区编码
                areaCode = StringUtils.isNotBlank(disCode) ? dto.getBranchCode() : dto.getDisCode();
                temp = modelMap.get(areaCode);
                // 数据集合不存在,默认新建数据集合
                if (CollectionUtils.isEmpty(temp)) {
                    temp = new ArrayList<ModelAnalyseInDto>();
                }
                temp.add(dto);
                // 按照对应的区域编码,保存到MAP中
                modelMap.put(areaCode, temp);
            }
            // 迭代区域编码, 按照月份组装对应区域12个月有效率数据
            Iterator<Entry<String, List<ModelAnalyseInDto>>> areaCodes = modelMap.entrySet().iterator();
            ModelAnalyseInDto firstModel;
            while (areaCodes.hasNext()) {
                temp = modelMap.get(areaCodes.next().getKey());
                // 默认取第一条数据,设置大区名称,分公司名称
                firstModel = temp.get(0);
                areaVo = new ModelValidInAreaVo();
                // 大区不为空时,返回分公司
                if (StringUtils.isNotBlank(disCode)) {
                    areaVo.setBranchCode(firstModel.getBranchCode());
                    areaVo.setBranchName(firstModel.getBranchName());
                } else {
                    areaVo.setDisCode(firstModel.getDisCode());
                    areaVo.setDisName(firstModel.getDisName());
                }
                // 转换12个月有效率数据
                areaVo.setRates(convertModelValid(months, temp));
                list.add(areaVo);
            }
        }
        // 保存记录
        resp.setList(list);
        LOGGER.info("queryModelValidArea exit, disCode={}", disCode);
        return resp;
    }
    
    
    /**
     * 查询有效性
     * 
     * @param disCode大区编码
     * @param regionCode 分公司编码
     */
    @Override
    public ModelValidAreaResponse queryModelValidAreaEx(String orgLevel, String disCode, String branchCode,
            String belongsDisCode, String belongsBranchCode, String storeType, String saleMonth, Integer pageNo,
            Integer pageSize) {
        ModelValidAreaResponse resp = new ModelValidAreaResponse();
        if (StringUtils.isBlank(saleMonth)) {
            resp.setTotalSize(0);
            resp.setList(new ArrayList<ModelValidAreaVo>());
            return resp;
        }
        List<ModelValidAreaVo> list = new ArrayList<ModelValidAreaVo>();
        Map<String, Object> queryMap = createQueryModelValidMap(orgLevel, disCode, branchCode, belongsDisCode,
                belongsBranchCode, storeType, saleMonth, pageNo, pageSize);
        
        // 设置标志位，前台使用
        if (OrgInfo.ORG_LEVEL.HQ_LEVEL.equals(orgLevel)) {
            resp.setLevel("1");
        }
        if (OrgInfo.ORG_LEVEL.REGION_LEVEL.equals(orgLevel)) {
            resp.setLevel("2");
            resp.setLevelCode(belongsDisCode);
        }
        if (OrgInfo.ORG_LEVEL.COMPANY_LEVEL.equals(orgLevel)) {
            resp.setLevel("3");
            resp.setLevelCode(belongsBranchCode);
        }

        Integer total = dalClient.queryForObject("MODEL_ANALYSE_IN.QUERY_MODEL_ANALYSE_COUNT", queryMap, Integer.class);
        resp.setTotalSize(null != total ? total : 0);
        // 没有数据，直接返回
        if (resp.getTotalSize() == 0) {
            resp.setList(list);
            return resp;
        }
        
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_ANALYSE", queryMap,
                ModelAnalyseInDto.class);
        if (CollectionUtils.isNotEmpty(models)) {
            Map<String, List<ModelAnalyseInDto>> modelMap = new HashMap<String, List<ModelAnalyseInDto>>();
            List<ModelAnalyseInDto> temp;
            ModelValidAreaVo areaVo;
            // 层级编码和名称
            String thisCode;
            String thisName;
            // 组装MAP集合
            for (ModelAnalyseInDto dto : models) {
                // 判断取分大区编码、公司编码,还是门店编码
                thisCode = StringUtils.isNotBlank(dto.getDisCode()) ? dto.getDisCode() : (StringUtils.isNotBlank(dto
                        .getBranchCode()) ? dto.getBranchCode() : dto.getStoreCode());
                temp = modelMap.get(thisCode);
                // 数据集合不存在,默认新建数据集合
                if (CollectionUtils.isEmpty(temp)) {
                    temp = new ArrayList<ModelAnalyseInDto>();
                }
                temp.add(dto);
                // 按照对应的区域编码,保存到MAP中
                modelMap.put(thisCode, temp);
            }
            for (Entry<String, List<ModelAnalyseInDto>> entry : modelMap.entrySet()) {
                List<ModelAnalyseInDto> dtoList = entry.getValue();
                if (CollectionUtils.isNotEmpty(dtoList)) {
                    thisCode = StringUtils.isNotBlank(dtoList.get(0).getDisCode()) ? dtoList.get(0).getDisCode()
                            : (StringUtils.isNotBlank(dtoList.get(0).getBranchCode()) ? dtoList.get(0).getBranchCode()
                                    : dtoList.get(0).getStoreCode());
                    thisName = StringUtils.isNotBlank(dtoList.get(0).getDisName()) ? dtoList.get(0).getDisName()
                            : (StringUtils.isNotBlank(dtoList.get(0).getBranchName()) ? dtoList.get(0).getBranchName()
                                    : dtoList.get(0).getStoreName());
                    areaVo = new ModelValidAreaVo();
                    areaVo.setHierCode(thisCode);
                    areaVo.setHierName(thisName);
                    // 有效系列数
                    BigDecimal validNum = BigDecimal.ZERO;
                    // 系列总数
                    BigDecimal modelTotalNum = BigDecimal.ZERO;
                    for (ModelAnalyseInDto dto : dtoList) {
                        String cateCode = dto.getCateCode();
                        if (StringUtils.isBlank(cateCode)
                                || StringUtils.isBlank(ConfigConstants.DEFAULT_CATE_MAP.get(cateCode))) {
                            continue;
                        }
                        Integer dtoValidNum = dto.getValidNum();
                        if (null == dtoValidNum) {
                            dtoValidNum = 0;
                        }
                        Integer dtoModelTotalNum = dto.getModelTotal();
                        if (null == dtoModelTotalNum) {
                            dtoModelTotalNum = 0;
                        }
                        validNum = validNum.add(new BigDecimal(dtoValidNum));
                        modelTotalNum = modelTotalNum.add(new BigDecimal(dtoModelTotalNum));
                        String rate = DJStringUtils.calculateRateString(String.valueOf(dtoValidNum),
                                String.valueOf(dtoModelTotalNum));
                        // 空调
                        if ("00001".equals(cateCode)) {
                            areaVo.setAirCondValidNum(String.valueOf(dtoValidNum));
                            areaVo.setAirCondTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setAirCondValidRate(rate);
                        } else if ("00002".equals(cateCode)) {
                            // 冰洗
                            areaVo.setIceWashValidNum(String.valueOf(dtoValidNum));
                            areaVo.setIceWashTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setIceWashValidRate(rate);
                        } else if ("00003".equals(cateCode)) {
                            // 黑电
                            areaVo.setBlackElecValidNum(String.valueOf(dtoValidNum));
                            areaVo.setBlackElecTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setBlackElecValidRate(rate);
                        } else if ("00004".equals(cateCode)) {
                            // 数码
                            areaVo.setDigitalValidNum(String.valueOf(dtoValidNum));
                            areaVo.setDigitalTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setDigitalValidRate(rate);
                        } else if ("00005".equals(cateCode)) {
                            // 电脑
                            areaVo.setCompValidNum(String.valueOf(dtoValidNum));
                            areaVo.setCompTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setCompValidRate(rate);
                        } else if ("00006".equals(cateCode)) {
                            // 通讯
                            areaVo.setCommValidNum(String.valueOf(dtoValidNum));
                            areaVo.setCommTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setCommValidRate(rate);
                        } else if ("00007".equals(cateCode)) {
                            // 生活电器
                            areaVo.setLifeElecValidNum(String.valueOf(dtoValidNum));
                            areaVo.setLifeElecTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setLifeElecValidRate(rate);
                        } else if ("00013".equals(cateCode)) {
                            // 厨卫
                            areaVo.setKitchenValidNum(String.valueOf(dtoValidNum));
                            areaVo.setKitchenTotalNum(String.valueOf(dtoModelTotalNum));
                            areaVo.setKitchenValidRate(rate);
                        }
                    }
                    areaVo.setValidNum(String.valueOf(validNum.intValue()));
                    areaVo.setModelTotalNum(String.valueOf(modelTotalNum.intValue()));
                    // 整体有效性
                    areaVo.setModelValidRate(DJStringUtils.calculateRateString(areaVo.getValidNum(),
                            areaVo.getModelTotalNum()));
                    list.add(areaVo);
                }
            }
        }
        // 设置默认值
        setParamsDefault(list);
        resp.setList(list);

        return resp;
    }
    
    private void setParamsDefault(List<ModelValidAreaVo> list) {
        // 样机有效性没有值，默认为0.0
        // 系列数默认为0 
        for (ModelValidAreaVo vo : list) {
            if (StringUtils.isBlank(vo.getAirCondValidNum())) {
                vo.setAirCondValidNum(NUM_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getAirCondTotalNum())) {
                vo.setAirCondTotalNum(NUM_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getAirCondValidRate())) {
                vo.setAirCondValidRate(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getIceWashValidNum())) {
                vo.setIceWashValidNum(NUM_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getIceWashTotalNum())) {
                vo.setIceWashTotalNum(NUM_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getIceWashValidRate())) {
                vo.setIceWashValidRate(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getBlackElecValidNum())) {
                vo.setBlackElecValidNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getBlackElecTotalNum())) {
                vo.setBlackElecTotalNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getBlackElecValidRate())) {
                vo.setBlackElecValidRate(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getDigitalValidNum())) {
                vo.setDigitalValidNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getDigitalTotalNum())) {
                vo.setDigitalTotalNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getDigitalValidRate())) {
                vo.setDigitalValidRate(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getCompValidNum())) {
                vo.setCompValidNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getCompTotalNum())) {
                vo.setCompTotalNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getCompValidRate())) {
                vo.setCompValidRate(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getCommValidNum())) {
                vo.setCommValidNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getCommTotalNum())) {
                vo.setCommTotalNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getCommValidRate())) {
                vo.setCommValidRate(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getLifeElecValidNum())) {
                vo.setLifeElecValidNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getLifeElecTotalNum())) {
                vo.setLifeElecTotalNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getLifeElecValidRate())) {
                vo.setLifeElecValidRate(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getKitchenValidNum())) {
                vo.setKitchenValidNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getKitchenTotalNum())) {
                vo.setKitchenTotalNum(RATE_DEFAULT);
            }
            if (StringUtils.isBlank(vo.getKitchenValidRate())) {
                vo.setKitchenValidRate(RATE_DEFAULT);
            }
        }
    }

    @Override
    public void exportModelValidAreaEx(String staffId, String orgLevel, String disCode, String branchCode,
            String belongsDisCode, String belongsBranchCode, String storeType, String saleMonth, Integer pageNo) {
        LOGGER.info(
                "exportModelValidAreaEx. staffId:{}, orgLevel:{}, disCode:{}, branchCode:{}, belongsDisCode:{}, belongsBranchCode:{}, storeType:{}, saleMonth:{}, pageNo:{}",
                new Object[] { staffId, orgLevel, disCode, branchCode, belongsDisCode, belongsBranchCode, storeType,
                        saleMonth, pageNo });
        ModelValidAreaResponse rsp = this.queryModelValidAreaEx(orgLevel, disCode, branchCode, belongsDisCode,
                belongsBranchCode, storeType, saleMonth, pageNo, getExptCSVLimit());
        List<ModelValidAreaVo> list = rsp.getList();
        if (CollectionUtils.isEmpty(list)) {
            LOGGER.warn("exportModelValidAreaEx. list is null");
            return;
        }
        String[] titles = new String[] { "层级名称", "整体有效系列数", "整体系列总数", "整体样效", "空调有效系列数", "空调系列总数", "空调样效", "冰洗有效系列数",
                "冰洗系列总数", "冰洗样效", "数码有效系列数", "数码系列总数", "数码样效", "黑电有效系列数", "黑电系列总数", "黑电样效", "通讯有效系列数", "通讯系列总数",
                "通讯样效", "电脑有效系列数", "电脑系列总数", "电脑样效", "生活电器有效系列数", "生活电器系列总数", "生活电器样效", "厨卫有效系列数", "厨卫系列总数", "厨卫样效" };
        List<List<String>> data = com.google.common.collect.Lists.transform(list,
                new Function<ModelValidAreaVo, List<String>>() {
                    @Override
                    public List<String> apply(ModelValidAreaVo input) {
                        List<String> msg = new ArrayList<String>();
                        msg.add(input.getHierName());
                        msg.add(input.getValidNum());
                        msg.add(input.getModelTotalNum());
                        msg.add(input.getModelValidRate() + RATE_FLAG);
                        msg.add(input.getAirCondValidNum());

                        msg.add(input.getAirCondTotalNum());
                        msg.add(input.getAirCondValidRate() + RATE_FLAG);
                        msg.add(input.getIceWashValidNum());
                        msg.add(input.getIceWashTotalNum());
                        msg.add(input.getIceWashValidRate() + RATE_FLAG);

                        msg.add(input.getDigitalValidNum());
                        msg.add(input.getDigitalTotalNum());
                        msg.add(input.getDigitalValidRate() + RATE_FLAG);
                        msg.add(input.getBlackElecValidNum());
                        msg.add(input.getBlackElecTotalNum());

                        msg.add(input.getBlackElecValidRate() + RATE_FLAG);
                        msg.add(input.getCommValidNum());
                        msg.add(input.getCommTotalNum());
                        msg.add(input.getCommValidRate() + RATE_FLAG);
                        msg.add(input.getCompValidNum());

                        msg.add(input.getCompTotalNum());
                        msg.add(input.getCompValidRate() + RATE_FLAG);
                        msg.add(input.getLifeElecValidNum());
                        msg.add(input.getLifeElecTotalNum());
                        msg.add(input.getLifeElecValidRate() + RATE_FLAG);

                        msg.add(input.getKitchenValidNum());
                        msg.add(input.getKitchenTotalNum());
                        msg.add(input.getKitchenValidRate() + RATE_FLAG);
                        return msg;
                    }
                });
        try {
            String fileName = "youxiaolvfenxi-" + pageNo;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, titles, data, "样机有效率分析" + pageNo,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("exportModelEffectEx failed.", e);
        }
    }
    
    @Override
    public void exportModelContributionAreaEx(String staffId, String orgLevel, String disCode, String branchCode,
            String belongsDisCode, String belongsBranchCode, String storeType, String saleMonth, Integer pageNo) {
        LOGGER.info(
                "exportModelContributionAreaEx.staffId:{}, orgLevel:{}, disCode:{}, branchCode:{}, belongsDisCode:{}, belongsBranchCode:{}, storeType:{}, saleMonth:{}, pageNo:{}",
                new Object[] { staffId, orgLevel, disCode, branchCode, belongsDisCode, belongsBranchCode, storeType,
                        saleMonth, pageNo });

        ModelContributionAreaExResponse rsp = this.queryModelContributionAreaEx(orgLevel, disCode, branchCode,
                belongsDisCode, belongsBranchCode, storeType, saleMonth, pageNo, getExptCSVLimit());

        List<ModelValidAreaVo> list = rsp.getList();
        if (CollectionUtils.isEmpty(list)) {
            LOGGER.warn("exportModelContributionAreaEx. list is null");
            return;
        }
        String[] titles = new String[] { "层级名称", "整体样机销售", "整体销售", "整体贡献率", "空调样机销售", "空调销售", "空调贡献率", "冰洗样机销售",
                "冰洗销售", "冰洗贡献率", "数码样机销售", "数码销售", "数码贡献率", "黑电样机销售", "黑电销售", "黑电贡献率", "通讯样机销售", "通讯销售", "通讯贡献率",
                "电脑样机销售", "电脑销售", "电脑贡献率", "生活电器样机销售", "生活电器销售", "生活电器贡献率", "厨卫样机销售", "厨卫销售", "厨卫贡献率" };
        List<List<String>> data = com.google.common.collect.Lists.transform(list,
                new Function<ModelValidAreaVo, List<String>>() {
                    @Override
                    public List<String> apply(ModelValidAreaVo input) {
                        List<String> msg = new ArrayList<String>();
                        msg.add(input.getHierName());
                        msg.add(input.getValidNum());
                        msg.add(input.getModelTotalNum());
                        msg.add(input.getModelValidRate() + RATE_FLAG);
                        msg.add(input.getAirCondValidNum());

                        msg.add(input.getAirCondTotalNum());
                        msg.add(input.getAirCondValidRate() + RATE_FLAG);
                        msg.add(input.getIceWashValidNum());
                        msg.add(input.getIceWashTotalNum());
                        msg.add(input.getIceWashValidRate() + RATE_FLAG);

                        msg.add(input.getDigitalValidNum());
                        msg.add(input.getDigitalTotalNum());
                        msg.add(input.getDigitalValidRate() + RATE_FLAG);
                        msg.add(input.getBlackElecValidNum());
                        msg.add(input.getBlackElecTotalNum());

                        msg.add(input.getBlackElecValidRate() + RATE_FLAG);
                        msg.add(input.getCommValidNum());
                        msg.add(input.getCommTotalNum());
                        msg.add(input.getCommValidRate() + RATE_FLAG);
                        msg.add(input.getCompValidNum());

                        msg.add(input.getCompTotalNum());
                        msg.add(input.getCompValidRate() + RATE_FLAG);
                        msg.add(input.getLifeElecValidNum());
                        msg.add(input.getLifeElecTotalNum());
                        msg.add(input.getLifeElecValidRate() + RATE_FLAG);

                        msg.add(input.getKitchenValidNum());
                        msg.add(input.getKitchenTotalNum());
                        msg.add(input.getKitchenValidRate() + RATE_FLAG);
                        return msg;
                    }
                });
        try {
            String fileName = "gongxianlvfenxi-" + pageNo;
            exportFileUtil.createCsvFileAndSendEmail(fileName, staffId, titles, data, "样机贡献率分析" + pageNo,
                    ExportConstants.OSSFileParams.FILE_CYCLE_TIME);
        } catch (Exception e) {
            LOGGER.error("exportModelContributionAreaEx failed.", e);
        }
    }
    
    private int getExptCSVLimit() {
        String limit = SCMConfigUtil.getConfig(ConfigConstants.MODEL_MANAGE_EXPORT_CSV_SIZE,
                ConfigConstants.DEFAULT_MODEL_MANAGE_EXPORT_CSV_SIZE);
        return Integer.valueOf(limit).intValue();
    }
    
    private Map<String, Object> createQueryModelValidMap(String orgLevel, String disCode, String branchCode,
            String belongsDisCode, String belongsBranchCode, String storeType, String saleMonth, Integer pageNo, Integer pageSize) {
        Map<String, Object> queryMap = new HashMap<String, Object>();
        
        // 首次进入页面，展示默认数据
        if (StringUtils.isBlank(disCode) && StringUtils.isBlank(branchCode)) {
            // 总部查下属43个大区，按大区分组
            if (OrgInfo.ORG_LEVEL.HQ_LEVEL.equals(orgLevel)) {
                queryMap.put("queryDis", 1);
            }
            // 大区查下属所有分公司，根据大区Code查询，按分公司分组
            if (OrgInfo.ORG_LEVEL.REGION_LEVEL.equals(orgLevel)) {
                queryMap.put("disCode", belongsDisCode);
                queryMap.put("queryBranch", 1);
            }
            // 分公司查下属门店，根据分公司Code查询，按门店分组
            if (OrgInfo.ORG_LEVEL.COMPANY_LEVEL.equals(orgLevel)) {
                queryMap.put("brandCode", belongsBranchCode);
                queryMap.put("queryStore", 1);
            }
        } else {
            // 点击链接查看分公司数据
            if (StringUtils.isNotBlank(disCode)) {
                queryMap.put("disCode", disCode);
                queryMap.put("queryBranch", 1);
            }
            // 点击链接查看门店数据
            if (StringUtils.isNotBlank(branchCode)) {
                queryMap.put("brandCode", branchCode);
                queryMap.put("queryStore", 1);
            }
        }
        // 门店类型storeType
        if (StringUtils.isNotBlank(storeType)) {
            List<String> types = new ArrayList<String>();
            // 门店
            if (String.valueOf(ModelConstant.STORE_TYPE_ELECTRIC).equals(storeType)) {
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_JQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SNYSD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CGD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_D4LSQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_EXPOCJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_BZD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQDQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_YD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CTD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_QJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SNSHGCD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_EXPOCJQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CJD);
                queryMap.put("storeTypes", types);
            }
            // 服务站
            if (String.valueOf(ModelConstant.STORE_TYPE_SERVICE).equals(storeType)) {
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_FWZ);
                queryMap.put("storeTypes", types);
            }
        }
        if (StringUtils.isNotBlank(saleMonth)) {
            queryMap.put("saleMonth", saleMonth);
        }
        if (null != pageSize && null != pageNo) {
            queryMap.put("startIndex", pageSize * (pageNo - 1));
            queryMap.put("pageSize", pageSize);
        }
        
        // 分页，查询层级codeList，大区编码集合or分公司编码集合or门店编码集合
        List<String> codes = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_ANALYSE_PAGE", queryMap,
                String.class);
        // 存在大区编码时,查询的是分公司下的数据
        if (CollectionUtils.isNotEmpty(codes)) {
            if (null != queryMap.get("queryDis") && "1".equals(queryMap.get("queryDis").toString())) {
                queryMap.put("disCodes", codes);
            }
            if (null != queryMap.get("queryBranch") && "1".equals(queryMap.get("queryBranch").toString())) {
                queryMap.put("brandCodes", codes);
            }
            if (null != queryMap.get("queryStore") && "1".equals(queryMap.get("queryStore").toString())) {
                queryMap.put("storeCodes", codes);
            }
        }
        
        return queryMap;
    }
    
    /**
     * 计算对应月份有效率 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param months
     * @param models
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ModelValidMonthVo> convertModelValid(List<String> months, List<ModelAnalyseInDto> models) {
        List<ModelValidMonthVo> list = new ArrayList<ModelValidMonthVo>();
        // 将记录按照月份组装成MAP对象
        Map<String, ModelAnalyseInDto> modelMap;
        if (CollectionUtils.isNotEmpty(models)) {
            modelMap = Maps.uniqueIndex(models, new Function<ModelAnalyseInDto, String>() {
                @Override
                public String apply(ModelAnalyseInDto from) {
                    // 利用月份确定数据
                    return from.getSaleMonth();
                }
            });
        } else {
            modelMap = new HashMap<String, ModelAnalyseInDto>();
        }
        // 将记录按照月份组装成MAP对象
        ModelAnalyseInDto model;
        ModelValidMonthVo vo;
        // 依次设置有效性数据
        for (String month : months) {
            vo = new ModelValidMonthVo();
            vo.setSaleMonth(month);
            // 从查询记录中取对应月份数据
            model = modelMap.get(month);
            // 不为空则计算有效性
            if (null != model) {
                // 计算
                vo.setRate(DJStringUtils.calculateRateDouble(model.getValidNum().toString(), model.getModelTotal()
                        .toString()));
                vo.setValidNum(model.getValidNum());
                vo.setModelTotal(model.getModelTotal());
            } else {
                // 为空则默认有效性0
                vo.setRate(0D);
                vo.setValidNum(Integer.valueOf("0"));
                vo.setModelTotal(Integer.valueOf("0"));
            }
            list.add(vo);
        }
        return list;
    }

    /**
     * 查询全国样机贡献率
     * 
     * @param saleMonth
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Override
    public ModelContributionResponse queryModelContribution(EmployeeInfo employeeInfo, String saleMonth, String storeType) {
        LOGGER.info("queryModelContribution enter, saleMonth={}, storeType={}", saleMonth, storeType);
        ModelContributionResponse resp = new ModelContributionResponse();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        queryMap.put("saleMonth", saleMonth);
        // 初始化8个品类，整理入参
        List<String> cates = new ArrayList<String>();
        cates.addAll(ConfigConstants.DEFAULT_CATE_MAP.keySet());
        queryMap.put("cates", cates);
        
        // 大区账号看大区数据
        if (OrgInfo.ORG_LEVEL.REGION_LEVEL.equals(employeeInfo.getOrgLevel())) {
            queryMap.put("disCode", employeeInfo.getRegion5Code());
        }
        // 分公司账号看分公司数据
        if (OrgInfo.ORG_LEVEL.COMPANY_LEVEL.equals(employeeInfo.getOrgLevel())) {
            queryMap.put("branchCode", employeeInfo.getBranchCode());
        }
        
        // 门店类型storeType
        if (StringUtils.isNotBlank(storeType)) {
            List<String> types = new ArrayList<String>();
            // 门店
            if (String.valueOf(ModelConstant.STORE_TYPE_ELECTRIC).equals(storeType)) {
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_JQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SNYSD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CGD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_D4LSQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_EXPOCJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_BZD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQDQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_YD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CTD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_QJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SNSHGCD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_EXPOCJQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CJD);
                queryMap.put("storeTypes", types);
            }
            // 服务站
            if (String.valueOf(ModelConstant.STORE_TYPE_SERVICE).equals(storeType)) {
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_FWZ);
                queryMap.put("storeTypes", types);
            }
        }
        
        // 查询样机销售数据
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_EX", queryMap,
                ModelAnalyseInDto.class);
        // 查询门店所有销售数据
        ModelAnalyseInDto sale = dalClient.queryForObject("MODEL_ANALYSE_IN.QUERY_STORE_CONTRIBUTION_EX", queryMap,
                ModelAnalyseInDto.class);
        // 设置返回数据
        resp.setList(convertModelContribution(models, sale));
        LOGGER.info("queryModelContribution exit, saleMonth={}", saleMonth);
        return resp;
    }

    /**
     * 转换样机贡献率 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param models
     * @param sales
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ModelContributionInVo> convertModelContribution(List<ModelAnalyseInDto> models, ModelAnalyseInDto sale) {
        if (null != sale && StringUtils.isNotBlank(sale.getSaleAmount())) {
            List<ModelContributionInVo> list = new ArrayList<ModelContributionInVo>();
            ModelContributionInVo modelContribution;
            // 门店样机销售总额
            String modelSaleAmount = "0.00";
            // 循环门店销售数据
            for (ModelAnalyseInDto model : models) {
                // 样机销售累加
                modelSaleAmount = DJStringUtils.addition(modelSaleAmount, model.getSaleAmount());
                // 设置品类信息
                modelContribution = new ModelContributionInVo();
                modelContribution.setCateCode(model.getCateCode());
                modelContribution.setCateName(model.getCateName());
                // 计算销售额,贡献率
                modelContribution.setSaleAmount(DJStringUtils.getTwoScale(model.getSaleAmount()));
                modelContribution
                        .setRate(DJStringUtils.calculateRateDouble(model.getSaleAmount(), sale.getSaleAmount()));

                list.add(modelContribution);
            }
            // 计算非样机销售额
            String otherSaleAmount = DJStringUtils.subtraction(sale.getSaleAmount(), modelSaleAmount);
            modelContribution = new ModelContributionInVo();
            modelContribution.setCateCode("-1");
            modelContribution.setCateName("非样机");
            // 计算销售额,贡献率
            modelContribution.setSaleAmount(otherSaleAmount);
            modelContribution.setRate(DJStringUtils.calculateRateDouble(otherSaleAmount, sale.getSaleAmount()));
            // 添加非样机贡献率
            list.add(modelContribution);
            return list;
        }
        return Collections.emptyList();
    }

    /**
     * 
     * 查询大区或者分公司样机贡献率
     * 
     * @param disCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Override
    public ModelContributionAreaResponse queryModelContributionArea(String belongRegion5Code, String disCode, int currIndex, int size) {
        LOGGER.info("queryModelContributionArea enter, disCode={}", disCode);
        ModelContributionAreaResponse resp = new ModelContributionAreaResponse();
        List<ModelContributionInAreaVo> list = new ArrayList<ModelContributionInAreaVo>();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        // 大区编码不为空
        if (StringUtils.isNotBlank(disCode)) {
            queryMap.put("disCode", disCode);
        }
        if (StringUtils.isNotBlank(belongRegion5Code)) {
            queryMap.put("belongRegion5Code", belongRegion5Code);
        }
        queryMap.put("currIndex", currIndex);
        queryMap.put("size", size);
        // 取前12个月数据(包含当前月)
        List<String> months = getTwelveMonths();
        queryMap.put("months", months);
        // 初始化8个品类，整理入参
        List<String> cates = new ArrayList<String>();
        cates.addAll(ConfigConstants.DEFAULT_CATE_MAP.keySet());
        queryMap.put("cates", cates);
        
        Integer total = dalClient.queryForObject("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_TOTAL", queryMap, Integer.class);
        // 设置总记录数
        resp.setTotalSize(null != total ? total : 0);
        
        // 查询出分页数据,大区集合or分公司集合
        List<String> codes = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_AREA_PAGE", queryMap,
                String.class);
        // 没有分页数据，直接返回
        if (CollectionUtils.isEmpty(codes)) {
            resp.setList(list);
            return resp;
        }
        // 存在大区编码时,查询的是分公司下的数据
        if (StringUtils.isNotBlank(disCode)) {
            queryMap.put("disCode", disCode);
            queryMap.put("branchCodes", codes);
        } else {
            queryMap.put("disCodes", codes);
        }
        
        // 查询库数据
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_AREA",
                queryMap, ModelAnalyseInDto.class);
        // 查询门店所有销售数据
        List<ModelAnalyseInDto> sales = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_AREA", queryMap,
                ModelAnalyseInDto.class);
        
        // 记录数不为空时
        if (CollectionUtils.isNotEmpty(sales)) {
            // 按照大区或分公司编码,组装对应12个月的数据集合MAP
            Map<String, List<ModelAnalyseInDto>> modelMap = new HashMap<String, List<ModelAnalyseInDto>>();
            Map<String, List<ModelAnalyseInDto>> saleMap = new HashMap<String, List<ModelAnalyseInDto>>();
            List<ModelAnalyseInDto> saleTemp;
            List<ModelAnalyseInDto> modelTemp;
            ModelContributionInAreaVo areaVo;
            // 组装MAP集合
            resetMap(saleMap, sales, disCode);
            // 样机数据不为空时
            if (CollectionUtils.isNotEmpty(models)) {
                // 初始化MAP数据
                resetMap(modelMap, models, disCode);
            }
            // 迭代区域编码, 按照月份组装对应区域12个月有效率数据
            Iterator<Entry<String, List<ModelAnalyseInDto>>> areaCodes = saleMap.entrySet().iterator();
            ModelAnalyseInDto firstModel;
            String areaCod;
            while (areaCodes.hasNext()) {
                areaCod = areaCodes.next().getKey();
                saleTemp = saleMap.get(areaCod);
                modelTemp = modelMap.get(areaCod);
                // 默认取第一条数据,设置大区名称,分公司名称
                firstModel = getFirstModel(saleTemp, disCode);
                areaVo = new ModelContributionInAreaVo();
                // 大区不为空时,返回分公司
                if (StringUtils.isNotBlank(disCode)) {
                    areaVo.setBranchCode(firstModel.getBranchCode());
                    areaVo.setBranchName(firstModel.getBranchName());
                } else {
                    areaVo.setDisCode(firstModel.getDisCode());
                    areaVo.setDisName(firstModel.getDisName());
                }
                // 转换12个月有效率数据
                areaVo.setRates(convertModelContribution(months, saleTemp, modelTemp));
                list.add(areaVo);
            }
        }
        // 保存记录
        resp.setList(list);
        LOGGER.info("queryModelContributionArea exit, disCode={}", disCode);
        return resp;
    }
    
    /**
     * 
     * 查询大区或者分公司样机贡献率
     * 
     * @param disCode
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Override
    public ModelContributionAreaExResponse queryModelContributionAreaEx(String orgLevel, String disCode,
            String brandCode, String belongsDisCode, String belongsBranchCode, String storeType, String saleMonth,
            Integer pageNo, Integer pageSize) {
        LOGGER.info(
                "queryModelContributionAreaEx enter, orgLevel:{},disCode:{},brandCode:{},belongsDisCode:{},belongsBranchCode:{},storeType:{},saleMonth:{}",
                new Object[] {orgLevel, disCode, brandCode, belongsDisCode, belongsBranchCode, storeType, saleMonth});

        ModelContributionAreaExResponse rsp = new ModelContributionAreaExResponse();
        List<ModelValidAreaVo> list = new ArrayList<ModelValidAreaVo>();

        if (StringUtils.isBlank(saleMonth)) {
            rsp.setTotalSize(0);
            rsp.setList(list);
            return rsp;
        }

        Map<String, Object> queryMap = createQueryModelContributionMap(orgLevel, disCode, brandCode, belongsDisCode,
                belongsBranchCode, storeType, saleMonth, pageNo, pageSize);
        
        // 设置标志位，前台使用
        if (OrgInfo.ORG_LEVEL.HQ_LEVEL.equals(orgLevel)) {
            rsp.setLevel("1");
        }
        if (OrgInfo.ORG_LEVEL.REGION_LEVEL.equals(orgLevel)) {
            rsp.setLevel("2");
            rsp.setLevelCode(belongsDisCode);
        }
        if (OrgInfo.ORG_LEVEL.COMPANY_LEVEL.equals(orgLevel)) {
            rsp.setLevel("3");
            rsp.setLevelCode(belongsBranchCode);
        }

        Integer total = dalClient.queryForObject("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_TOTAL_EX", queryMap,
                Integer.class);
        // 设置总记录数
        rsp.setTotalSize(null != total ? total : 0);
        // 为空直接返回
        if (rsp.getTotalSize() == 0) {
            rsp.setList(list);
            return rsp;
        }

        // 查询库数据 MODEL_ANALYSE_IN
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_AREA_EX",
                queryMap, ModelAnalyseInDto.class);
        // 查询门店所有销售数据 BI_STORE_SALE_CATE_MONTH
        List<ModelAnalyseInDto> sales = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_AREA_EX", queryMap,
                ModelAnalyseInDto.class);

        Map<String, List<ModelAnalyseInDto>> modelsMap = new HashMap<String, List<ModelAnalyseInDto>>();
        Map<String, List<ModelAnalyseInDto>> salesMap = new HashMap<String, List<ModelAnalyseInDto>>();
        // 层级编码和名称
        String thisCode;
        String thisName;
        List<ModelAnalyseInDto> temp;
        if (CollectionUtils.isNotEmpty(models)) {
            for (ModelAnalyseInDto model : models) {
                // 判断取分大区编码、公司编码,还是门店编码
                thisCode = StringUtils.isNotBlank(model.getDisCode()) ? model.getDisCode() : (StringUtils
                        .isNotBlank(model.getBranchCode()) ? model.getBranchCode() : model.getStoreCode());
                temp = modelsMap.get(thisCode);
                // 数据集合不存在,默认新建数据集合
                if (CollectionUtils.isEmpty(temp)) {
                    temp = new ArrayList<ModelAnalyseInDto>();
                }
                temp.add(model);
                // 按照对应的区域编码,保存到MAP中
                modelsMap.put(thisCode, temp);
            }
        }
        if (CollectionUtils.isNotEmpty(sales)) {
            for (ModelAnalyseInDto sale : sales) {
                thisCode = StringUtils.isNotBlank(sale.getDisCode()) ? sale.getDisCode() : (StringUtils.isNotBlank(sale
                        .getBranchCode()) ? sale.getBranchCode() : sale.getStoreCode());
                temp = salesMap.get(thisCode);
                if (CollectionUtils.isEmpty(temp)) {
                    temp = new ArrayList<ModelAnalyseInDto>();
                }
                temp.add(sale);
                // 按照对应的区域编码,保存到MAP中
                salesMap.put(thisCode, temp);
            }
        }

        ModelValidAreaVo areaVo;
        for (Entry<String, List<ModelAnalyseInDto>> entry : salesMap.entrySet()) {
            List<ModelAnalyseInDto> dtoList = entry.getValue();
            if (CollectionUtils.isNotEmpty(dtoList)) {
                thisCode = StringUtils.isNotBlank(dtoList.get(0).getDisCode()) ? dtoList.get(0).getDisCode()
                        : (StringUtils.isNotBlank(dtoList.get(0).getBranchCode()) ? dtoList.get(0).getBranchCode()
                                : dtoList.get(0).getStoreCode());
                thisName = StringUtils.isNotBlank(dtoList.get(0).getDisName()) ? dtoList.get(0).getDisName()
                        : (StringUtils.isNotBlank(dtoList.get(0).getBranchName()) ? dtoList.get(0).getBranchName()
                                : dtoList.get(0).getStoreName());
                areaVo = new ModelValidAreaVo();
                areaVo.setHierCode(thisCode);
                areaVo.setHierName(thisName);
                // 品类样机金额
                BigDecimal modelSaleTotal = BigDecimal.ZERO;
                // 品类销售额
                BigDecimal saleTotal = BigDecimal.ZERO;
                for (ModelAnalyseInDto dto : dtoList) {
                    String cateCode = dto.getCateCode();
                    if (StringUtils.isBlank(cateCode)
                            || StringUtils.isBlank(ConfigConstants.DEFAULT_CATE_MAP.get(cateCode))) {
                        continue;
                    }

                    // 品类销售金额
                    String saleAmount = dto.getSaleAmount();
                    if (null == saleAmount) {
                        saleAmount = "0";
                    }

                    // 样机金额
                    String modelAmount = "0";
                    List<ModelAnalyseInDto> modelList = modelsMap.get(thisCode);
                    if (CollectionUtils.isNotEmpty(modelList)) {
                        for (ModelAnalyseInDto m : modelList) {
                            if (cateCode.equals(m.getCateCode())) {
                                modelAmount = m.getSaleAmount();
                                break;
                            }
                        }
                    }

                    modelSaleTotal = modelSaleTotal.add(new BigDecimal(modelAmount));
                    saleTotal = saleTotal.add(new BigDecimal(saleAmount));
                    String rate = DJStringUtils.calculateRateString(modelAmount, saleAmount);
                    // 空调
                    if ("00001".equals(cateCode)) {
                        areaVo.setAirCondValidNum(String.valueOf(modelAmount));
                        areaVo.setAirCondTotalNum(String.valueOf(saleAmount));
                        areaVo.setAirCondValidRate(rate);
                    } else if ("00002".equals(cateCode)) {
                        // 冰洗
                        areaVo.setIceWashValidNum(String.valueOf(modelAmount));
                        areaVo.setIceWashTotalNum(String.valueOf(saleAmount));
                        areaVo.setIceWashValidRate(rate);
                    } else if ("00003".equals(cateCode)) {
                        // 黑电
                        areaVo.setBlackElecValidNum(String.valueOf(modelAmount));
                        areaVo.setBlackElecTotalNum(String.valueOf(saleAmount));
                        areaVo.setBlackElecValidRate(rate);
                    } else if ("00004".equals(cateCode)) {
                        // 数码
                        areaVo.setDigitalValidNum(String.valueOf(modelAmount));
                        areaVo.setDigitalTotalNum(String.valueOf(saleAmount));
                        areaVo.setDigitalValidRate(rate);
                    } else if ("00005".equals(cateCode)) {
                        // 电脑
                        areaVo.setCompValidNum(String.valueOf(modelAmount));
                        areaVo.setCompTotalNum(String.valueOf(saleAmount));
                        areaVo.setCompValidRate(rate);
                    } else if ("00006".equals(cateCode)) {
                        // 通讯
                        areaVo.setCommValidNum(String.valueOf(modelAmount));
                        areaVo.setCommTotalNum(String.valueOf(saleAmount));
                        areaVo.setCommValidRate(rate);
                    } else if ("00007".equals(cateCode)) {
                        // 生活电器
                        areaVo.setLifeElecValidNum(String.valueOf(modelAmount));
                        areaVo.setLifeElecTotalNum(String.valueOf(saleAmount));
                        areaVo.setLifeElecValidRate(rate);
                    } else if ("00013".equals(cateCode)) {
                        // 厨卫
                        areaVo.setKitchenValidNum(String.valueOf(modelAmount));
                        areaVo.setKitchenTotalNum(String.valueOf(saleAmount));
                        areaVo.setKitchenValidRate(rate);
                    }
                }
                areaVo.setValidNum(String.valueOf(modelSaleTotal));
                areaVo.setModelTotalNum(String.valueOf(saleTotal));
                // 整体贡献率
                areaVo.setModelValidRate(DJStringUtils.calculateRateString(areaVo.getValidNum(),
                        areaVo.getModelTotalNum()));
                list.add(areaVo);
            }
        }
        // 设置默认值
        setParamsDefault(list);
        rsp.setList(list);
        LOGGER.info("queryModelContributionArea exit, disCode={}", disCode);
        return rsp;
    }
 
    private Map<String, Object> createQueryModelContributionMap(String orgLevel, String disCode, String brandCode,
            String belongsDisCode, String belongsBranchCode, String storeType, String saleMonth, Integer pageNo,
            Integer pageSize) {
        Map<String, Object> queryMap = new HashMap<String, Object>();
        // 首次进入页面，展示默认数据
        if (StringUtils.isBlank(disCode) && StringUtils.isBlank(brandCode)) {
            // 总部查下属43个大区，按大区分组
            if (OrgInfo.ORG_LEVEL.HQ_LEVEL.equals(orgLevel)) {
                queryMap.put("queryDis", 1);
            }
            // 大区查下属所有分公司，根据大区Code查询，按分公司分组
            if (OrgInfo.ORG_LEVEL.REGION_LEVEL.equals(orgLevel)) {
                queryMap.put("disCode", belongsDisCode);
                queryMap.put("queryBranch", 1);
            }
            // 分公司查下属门店，根据分公司Code查询，按门店分组
            if (OrgInfo.ORG_LEVEL.COMPANY_LEVEL.equals(orgLevel)) {
                queryMap.put("brandCode", belongsBranchCode);
                queryMap.put("queryStore", 1);
            }
        } else {
            // 点击链接查看分公司数据
            if (StringUtils.isNotBlank(disCode)) {
                queryMap.put("disCode", disCode);
                queryMap.put("queryBranch", 1);
            }
            // 点击链接查看门店数据
            if (StringUtils.isNotBlank(brandCode)) {
                queryMap.put("brandCode", brandCode);
                queryMap.put("queryStore", 1);
            }
        }
        
        // 门店类型storeType
        if (StringUtils.isNotBlank(storeType)) {
            List<String> types = new ArrayList<String>();
            // 门店
            if (String.valueOf(ModelConstant.STORE_TYPE_ELECTRIC).equals(storeType)) {
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_JQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SNYSD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CGD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_D4LSQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_EXPOCJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_BZD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQDQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_YD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CTD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_QJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_SNSHGCD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_EXPOCJQJD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_DQD);
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_CJD);
                queryMap.put("storeTypes", types);
            }
            // 服务站
            if (String.valueOf(ModelConstant.STORE_TYPE_SERVICE).equals(storeType)) {
                types.add(ModelConstant.STORE_TYPE_INFOS.STORE_TYPE_FWZ);
                queryMap.put("storeTypes", types);
            }
        }
        
        if (StringUtils.isNotBlank(saleMonth)) {
            queryMap.put("saleMonth", saleMonth);
        }
        if (null != pageSize && null != pageNo) {
            queryMap.put("startIndex", pageSize * (pageNo - 1));
            queryMap.put("pageSize", pageSize);
        }
        
        // 初始化8个品类，整理入参
        List<String> cates = new ArrayList<String>();
        cates.addAll(ConfigConstants.DEFAULT_CATE_MAP.keySet());
        queryMap.put("cates", cates);
        
        // 查询出分页数据,大区集合or分公司集合or门店集合
        List<String> codes = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_AREA_PAGE_EX", queryMap,
                String.class);
        // 存在大区编码时,查询的是分公司下的数据
        if (CollectionUtils.isNotEmpty(codes)) {
            if (null != queryMap.get("queryDis") && "1".equals(queryMap.get("queryDis").toString())) {
                queryMap.put("disCodes", codes);
            }
            if (null != queryMap.get("queryBranch") && "1".equals(queryMap.get("queryBranch").toString())) {
                queryMap.put("brandCodes", codes);
            }
            if (null != queryMap.get("queryStore") && "1".equals(queryMap.get("queryStore").toString())) {
                queryMap.put("storeCodes", codes);
            }
        }
        
        return queryMap;
    }

    /**
     * 
     * 功能描述: 取分公司或者大区编码和名称<br>
     * 〈功能详细描述〉
     *
     * @param list
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private ModelAnalyseInDto getFirstModel(List<ModelAnalyseInDto> list, String disCode) {
        ModelAnalyseInDto temp = list.get(0);// 默认取列表中的第一个元素
        for (ModelAnalyseInDto dto : list) {
            if (StringUtils.isNotBlank(disCode)) {
                // 大区不为空时,判断分公司
                if (StringUtils.isNotBlank(dto.getBranchCode()) && 
                        StringUtils.isNotBlank(dto.getBranchName())) {
                    // 循环取值的目的在于，DB中查询出来的月份对应数据中存在某些月份大区分公司，名称为空的情况
                    // 顾做一个容错处理，遍历整个list,返回一个编码和名称均不为空的数据，如果整个list都没有，那就只能默认返回第一个，木有法子啦 
                    temp = dto;
                    break;
                }
            } else {
                if (StringUtils.isNotBlank(dto.getDisCode()) && 
                        StringUtils.isNotBlank(dto.getDisName())) {
                    temp = dto;
                    break;
                }
            }
        }
        
        return temp;
    }
    
    /**
     * 将集合转换成MAP对象
     * 
     * @param map
     * @param list
     * @param disCode
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void resetMap(Map<String, List<ModelAnalyseInDto>> map, List<ModelAnalyseInDto> list, String disCode) {
        String areaCode;
        List<ModelAnalyseInDto> temp;
        for (ModelAnalyseInDto dto : list) {
            // 根据传参大区编码,判断取分公司编码,还是大区编码
            areaCode = StringUtils.isNotBlank(disCode) ? dto.getBranchCode() : dto.getDisCode();
            temp = map.get(areaCode);
            // 数据集合不存在,默认新建数据集合
            if (CollectionUtils.isEmpty(temp)) {
                temp = new ArrayList<ModelAnalyseInDto>();
            }
            temp.add(dto);
            // 按照对应的区域编码,保存到MAP中
            map.put(areaCode, temp);
        }
    }
    
    /**
     * 将集合转换成MAP对象
     * 
     * @param map
     * @param list
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private void resetStoreMap(Map<String, List<ModelAnalyseInDto>> map, List<ModelAnalyseInDto> list) {
        String areaCode;
        List<ModelAnalyseInDto> temp;
        for (ModelAnalyseInDto dto : list) {
            // 根据传参大区编码,判断取分公司编码,还是大区编码
            areaCode = dto.getStoreCode();
            temp = map.get(areaCode);
            // 数据集合不存在,默认新建数据集合
            if (CollectionUtils.isEmpty(temp)) {
                temp = new ArrayList<ModelAnalyseInDto>();
            }
            temp.add(dto);
            // 按照对应的区域编码,保存到MAP中
            map.put(areaCode, temp);
        }
    }

    /**
     * 计算对应月份有效率 功能描述: <br>
     * 〈功能详细描述〉
     * 
     * @param months
     * @param models
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ModelContributionMonthVo> convertModelContribution(List<String> months, List<ModelAnalyseInDto> sales,
            List<ModelAnalyseInDto> models) {
        List<ModelContributionMonthVo> list = new ArrayList<ModelContributionMonthVo>();
        // 将记录按照月份组装成MAP对象
        Map<String, ModelAnalyseInDto> saleMap = Maps.uniqueIndex(sales, new Function<ModelAnalyseInDto, String>() {
            @Override
            public String apply(ModelAnalyseInDto from) {
                // 利用月份确定数据
                return from.getSaleMonth();
            }
        });
        Map<String, ModelAnalyseInDto> modelMap;
        // 样机销售数据不为空
        if (CollectionUtils.isNotEmpty(models)) {
            modelMap = Maps.uniqueIndex(models, new Function<ModelAnalyseInDto, String>() {
                @Override
                public String apply(ModelAnalyseInDto from) {
                    // 利用月份确定数据
                    return from.getSaleMonth();
                }
            });
        } else {
            modelMap = new HashMap<String, ModelAnalyseInDto>();
        }
        ModelAnalyseInDto sale;
        ModelAnalyseInDto model;
        ModelContributionMonthVo vo;
        // 依次设置有效性数据
        for (String month : months) {
            vo = new ModelContributionMonthVo();
            vo.setSaleMonth(month);
            // 从查询记录中取对应月份数据
            sale = saleMap.get(month);
            model = modelMap.get(month);
            // 不为空则计算有效性
            if (null != sale && null != model) {
                // 计算
                vo.setRate(DJStringUtils.calculateRateDouble(model.getSaleAmount(), sale.getSaleAmount()));
            } else {
                // 为空则默认有效性0
                vo.setRate(0D);
            }
            list.add(vo);
        }
        return list;
    }

    /**
     * 
     * 查询样机销售TOP排行
     * 
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Override
    public ModelSaleTopResponse queryModelContributionTop(int currIndex, int size) {
        LOGGER.info("queryModelContributionTop enter");
        ModelSaleTopResponse resp = new ModelSaleTopResponse();
        List<ModelSaleTopInVo> list = new ArrayList<ModelSaleTopInVo>();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        queryMap.put("currIndex", currIndex);
        queryMap.put("size", size);
        // 取上月的排行
        queryMap.put("saleMonth", DateUtils.getThisMonth());
        // 查询库数据
        List<ModelSaleTopInDto> modelTops = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_TOP",
                queryMap, ModelSaleTopInDto.class);
        Integer total = dalClient.queryForObject("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_TOP_TOTAL", queryMap,
                Integer.class);
        // 设置总记录数
        resp.setTotalSize(null != total ? total : 0);
        if (CollectionUtils.isNotEmpty(modelTops)) {
            ModelSaleTopInVo vo;
            for (ModelSaleTopInDto dto : modelTops) {
                vo = new ModelSaleTopInVo();
                vo.setCateCode(dto.getCateCode());
                vo.setCateName(dto.getCateName());
                vo.setBrandCode(dto.getBrandCode());
                vo.setBrandName(dto.getBrandName());
                vo.setCommCode(dto.getCommCode());
                vo.setCommName(dto.getCommName());
                vo.setModelTotal(dto.getModelTotal());
                vo.setSaleNum(dto.getSaleNum());
                vo.setRate(DJStringUtils
                        .calculateRateDouble(dto.getValidNum().toString(), dto.getModelCnt().toString()));
                list.add(vo);
            }
        }
        // 设置结果
        resp.setList(list);
        LOGGER.info("queryModelContributionTop exit");
        return resp;
    }

    /**
     * 查询大区或分公司样机销售贡献率
     */
    @Override
    public ExportCsvFileVo queryModelContributionArea(final String disCode) {
        LOGGER.info("queryModelContributionArea enter, disCode={}", disCode);
        ExportCsvFileVo file = new ExportCsvFileVo();
        List<ModelContributionInAreaVo> list = new ArrayList<ModelContributionInAreaVo>();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        // 大区编码不为空
        if (StringUtils.isNotBlank(disCode)) {
            queryMap.put("disCode", disCode);
        }
        // 取前12个月数据(包含当前月)
        List<String> months = getTwelveMonths();
        queryMap.put("months", months);
        // 初始化8个品类，整理入参
        List<String> cates = new ArrayList<String>();
        cates.addAll(ConfigConstants.DEFAULT_CATE_MAP.keySet());
        queryMap.put("cates", cates);
        // 查询库数据
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_AREA",
                queryMap, ModelAnalyseInDto.class);
        // 查询门店所有销售数据
        List<ModelAnalyseInDto> sales = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_AREA", queryMap,
                ModelAnalyseInDto.class);
        // 记录数不为空时
        if (CollectionUtils.isNotEmpty(sales)) {
            // 按照大区或分公司编码,组装对应12个月的数据集合MAP
            Map<String, List<ModelAnalyseInDto>> modelMap = new HashMap<String, List<ModelAnalyseInDto>>();
            Map<String, List<ModelAnalyseInDto>> saleMap = new HashMap<String, List<ModelAnalyseInDto>>();
            List<ModelAnalyseInDto> saleTemp;
            List<ModelAnalyseInDto> modelTemp;
            ModelContributionInAreaVo areaVo;
            // 组装MAP集合
            resetMap(saleMap, sales, disCode);
            // 样机数据不为空时
            if (CollectionUtils.isNotEmpty(models)) {
                // 初始化MAP数据
                resetMap(modelMap, models, disCode);
            }
            // 迭代区域编码, 按照月份组装对应区域12个月有效率数据
            Iterator<Entry<String, List<ModelAnalyseInDto>>> areaCodes = saleMap.entrySet().iterator();
            ModelAnalyseInDto firstModel;
            String areaCod;
            while (areaCodes.hasNext()) {
                areaCod = areaCodes.next().getKey();
                saleTemp = saleMap.get(areaCod);
                modelTemp = modelMap.get(areaCod);
                // 默认取第一条数据,设置大区名称,分公司名称
                firstModel = saleTemp.get(0);
                areaVo = new ModelContributionInAreaVo();
                // 大区不为空时,返回分公司
                if (StringUtils.isNotBlank(disCode)) {
                    areaVo.setBranchCode(firstModel.getBranchCode());
                    areaVo.setBranchName(firstModel.getBranchName());
                } else {
                    areaVo.setDisCode(firstModel.getDisCode());
                    areaVo.setDisName(firstModel.getDisName());
                }
                // 转换12个月有效率数据
                areaVo.setRates(convertModelContribution(months, saleTemp, modelTemp));
                list.add(areaVo);
            }
        }
        
        //170419 获取分公司下门店/大区下门店的贡献率信息
        List<ModelContributionInAreaVo> newList = new ArrayList<ModelContributionInAreaVo>();
        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, Object> queryStoreMap = new HashMap<String, Object>();
            queryStoreMap.put("months", months);
            queryStoreMap.put("cates", cates);
            List<ModelAnalyseInDto> storeModels;
            List<ModelAnalyseInDto> storeSales;
            for (ModelContributionInAreaVo vo :list) {
                newList.add(vo);
                if (StringUtils.isNotBlank(disCode)) {
                    queryStoreMap.remove("disCode");
                    queryStoreMap.put("branchCode", vo.getBranchCode());
                } else {
                    queryStoreMap.remove("branchCode");
                    queryStoreMap.put("disCode", vo.getDisCode());
                }
                storeModels = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_STORE",
                        queryStoreMap, ModelAnalyseInDto.class);
                storeSales = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_CONTRIBUTION_STORE", queryStoreMap,
                        ModelAnalyseInDto.class);
                newList.addAll(fixModelContributionData(storeSales, storeModels, disCode, months));
            }
        }
        list = newList;
        
        // 文件头信息
        Object[] header = new Object[14];
        if (StringUtils.isBlank(disCode)) {
            header[0] = "大区/门店编码";
            header[1] = "大区/门店名称";
        } else {
            header[0] = "分公司/门店编码";
            header[1] = "分公司/门店名称";
        }
        // 月份头信息
        for (int i = 0; i < months.size(); i++) {
            header[i + 2] = months.get(i);
        }
        file.setHeader(header);
        // 文件体信息
        List<List<String>> data = Lists.transform(list, new Function<ModelContributionInAreaVo, List<String>>() {
            @Override
            public List<String> apply(ModelContributionInAreaVo input) {
                List<String> msg = new ArrayList<String>();
                if (StringUtils.isNotBlank(input.getStoreCode())) {
                    msg.add(input.getStoreCode());
                    msg.add(input.getStoreName());
                } else if (StringUtils.isNotBlank(disCode)) {
                    msg.add(input.getBranchCode());
                    msg.add(input.getBranchName());
                } else {
                    msg.add(input.getDisCode());
                    msg.add(input.getDisName());
                }
                if (CollectionUtils.isNotEmpty(input.getRates())) {
                    for (ModelContributionMonthVo rate : input.getRates()) {
                        msg.add(rate.getRate() + "%");
                    }
                }
                return msg;
            }
        });
        file.setData(data);
        // 保存记录
        LOGGER.info("queryModelContributionArea exit, disCode={}", disCode);
        return file;
    }

    /**
     * 
     * 功能描述: 门店贡献率计算<br>
     * 〈功能详细描述〉
     *
     * @param storeSales
     * @param storeModels
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ModelContributionInAreaVo> fixModelContributionData(List<ModelAnalyseInDto> storeSales,
            List<ModelAnalyseInDto> storeModels, String disCode, List<String> months) {
        List<ModelContributionInAreaVo> list = new ArrayList<ModelContributionInAreaVo>();

        if (CollectionUtils.isNotEmpty(storeSales)) {
            // 按照大区或分公司编码,组装对应12个月的数据集合MAP
            Map<String, List<ModelAnalyseInDto>> modelMap = new HashMap<String, List<ModelAnalyseInDto>>();
            Map<String, List<ModelAnalyseInDto>> saleMap = new HashMap<String, List<ModelAnalyseInDto>>();
            List<ModelAnalyseInDto> saleTemp;
            List<ModelAnalyseInDto> modelTemp;
            ModelContributionInAreaVo areaVo;
            // 组装MAP集合
            resetStoreMap(saleMap, storeSales);
            // 样机数据不为空时
            if (CollectionUtils.isNotEmpty(storeModels)) {
                // 初始化MAP数据
                resetStoreMap(modelMap, storeModels);
            }
            // 迭代区域编码, 按照月份组装对应区域12个月有效率数据
            Iterator<Entry<String, List<ModelAnalyseInDto>>> areaCodes = saleMap.entrySet().iterator();
            ModelAnalyseInDto firstModel;
            String areaCod;
            while (areaCodes.hasNext()) {
                areaCod = areaCodes.next().getKey();
                saleTemp = saleMap.get(areaCod);
                modelTemp = modelMap.get(areaCod);
                // 默认取第一条数据,设置大区名称,分公司名称
                firstModel = saleTemp.get(0);
                areaVo = new ModelContributionInAreaVo();
                areaVo.setStoreCode(firstModel.getStoreCode());
                areaVo.setStoreName(firstModel.getStoreName());
                // 转换12个月有效率数据
                areaVo.setRates(convertModelContribution(months, saleTemp, modelTemp));
                list.add(areaVo);
            }
        }

        return list;
    }

    /**
     * 查询大区或分公司样机销售有效率
     */
    @Override
    public ExportCsvFileVo queryModelValidArea(final String disCode, String belongDisCode) {
        LOGGER.info("queryModelValidArea enter, disCode={}", disCode);
        ExportCsvFileVo file = new ExportCsvFileVo();
        List<ModelValidInAreaVo> list = new ArrayList<ModelValidInAreaVo>();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        // 大区编码不为空时
        if (StringUtils.isNotBlank(disCode)) {
            queryMap.put("disCode", disCode);
        }
        if (StringUtils.isNotBlank(belongDisCode)) {
            queryMap.put("belongDisCode", belongDisCode);
        }
        // 取前12个月数据(包含当前月)
        List<String> months = getTwelveMonths();
        queryMap.put("months", months);
        // 查询库数据
        List<ModelAnalyseInDto> models = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_VALID_AREA", queryMap,
                ModelAnalyseInDto.class);
        // 记录数不为空时
        if (CollectionUtils.isNotEmpty(models)) {
            // 按照大区或分公司编码,组装对应12个月的数据集合MAP
            Map<String, List<ModelAnalyseInDto>> modelMap = new HashMap<String, List<ModelAnalyseInDto>>();
            List<ModelAnalyseInDto> temp;
            ModelValidInAreaVo areaVo;
            String areaCode;
            // 组装MAP集合
            for (ModelAnalyseInDto dto : models) {
                // 根据传参大区编码,判断取分公司编码,还是大区编码
                areaCode = StringUtils.isNotBlank(disCode) ? dto.getBranchCode() : dto.getDisCode();
                temp = modelMap.get(areaCode);
                // 数据集合不存在,默认新建数据集合
                if (CollectionUtils.isEmpty(temp)) {
                    temp = new ArrayList<ModelAnalyseInDto>();
                }
                temp.add(dto);
                // 按照对应的区域编码,保存到MAP中
                modelMap.put(areaCode, temp);
            }
            // 迭代区域编码, 按照月份组装对应区域12个月有效率数据
            Iterator<Entry<String, List<ModelAnalyseInDto>>> areaCodes = modelMap.entrySet().iterator();
            ModelAnalyseInDto firstModel;
            while (areaCodes.hasNext()) {
                temp = modelMap.get(areaCodes.next().getKey());
                // 默认取第一条数据,设置大区名称,分公司名称
                firstModel = temp.get(0);
                areaVo = new ModelValidInAreaVo();
                // 大区不为空时,返回分公司
                if (StringUtils.isNotBlank(disCode)) {
                    areaVo.setBranchCode(firstModel.getBranchCode());
                    areaVo.setBranchName(firstModel.getBranchName());
                } else {
                    areaVo.setDisCode(firstModel.getDisCode());
                    areaVo.setDisName(firstModel.getDisName());
                }
                // 转换12个月有效率数据
                areaVo.setRates(convertModelValid(months, temp));
                list.add(areaVo);
            }
        }
        
        //170412 获取分公司下门店/大区下门店的有效性信息
        List<ModelValidInAreaVo> newList = new ArrayList<ModelValidInAreaVo>();
        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, Object> queryStoreMap = new HashMap<String, Object>();
            List<ModelAnalyseInDto> storeDtos;
            for (ModelValidInAreaVo vo : list) {
                newList.add(vo);
                // disCode有值，获取分公司下的门店
                if (StringUtils.isNotBlank(disCode)) {
                    queryStoreMap.clear();
                    queryStoreMap.put("branchCodes", vo.getBranchCode());
                    queryStoreMap.put("months", months);
                    storeDtos = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_VALID_AREA_STORE", queryStoreMap,
                            ModelAnalyseInDto.class);
                    if (CollectionUtils.isNotEmpty(storeDtos)) {
                        // 将转换后的数据放到newList
                        newList.addAll(fixModelValidData(months, storeDtos));
                    }
                } else {
                    queryStoreMap.clear();
                    queryStoreMap.put("disCodes", vo.getDisCode());
                    queryStoreMap.put("months", months);
                    storeDtos = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_VALID_AREA_STORE", queryStoreMap,
                            ModelAnalyseInDto.class);
                    if (CollectionUtils.isNotEmpty(storeDtos)) {
                        // 将转换后的数据放到newList
                        newList.addAll(fixModelValidData(months, storeDtos));
                    }
                }
            }
        }
        
        list = newList;
        
        // 文件头信息
        Object[] header = new Object[14];
        if (StringUtils.isNotBlank(disCode)) {
            header[0] = "分公司/门店编码";
            header[1] = "分公司/门店名称";
        } else {
            header[0] = "大区/门店编码";
            header[1] = "大区/门店名称";
        }
        // 月份头信息
        for (int i = 0; i < months.size(); i++) {
            header[i + 2] = months.get(i);
        }
        file.setHeader(header);
        // 文件体信息
        List<List<String>> data = Lists.transform(list, new Function<ModelValidInAreaVo, List<String>>() {
            @Override
            public List<String> apply(ModelValidInAreaVo input) {
                List<String> msg = new ArrayList<String>();
                if (StringUtils.isNotBlank(input.getStoreCode())) {
                    msg.add(input.getStoreCode());
                    msg.add(input.getStoreName());
                } else if (StringUtils.isNotBlank(disCode)) {
                    msg.add(input.getBranchCode());
                    msg.add(input.getBranchName());
                } else {
                    msg.add(input.getDisCode());
                    msg.add(input.getDisName());
                }
                if (CollectionUtils.isNotEmpty(input.getRates())) {
                    for (ModelValidMonthVo rate : input.getRates()) {
                        msg.add(rate.getRate() + "%");
                    }
                }
                return msg;
            }
        });
        file.setData(data);
        LOGGER.info("queryModelValidArea exit, disCode={}", disCode);
        return file;
    }

    /**
     * 
     * 功能描述: 门店有效性计算<br>
     * 〈功能详细描述〉
     *
     * @param months
     * @param storeDtos
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<ModelValidInAreaVo> fixModelValidData(List<String> months, List<ModelAnalyseInDto> storeDtos) {
        List<ModelValidInAreaVo> list = new ArrayList<ModelValidInAreaVo>();
        // 按照大区或分公司编码,组装对应12个月的数据集合MAP
        Map<String, List<ModelAnalyseInDto>> modelMap = new HashMap<String, List<ModelAnalyseInDto>>();
        List<ModelAnalyseInDto> temp;
        ModelValidInAreaVo areaVo;
        String areaCode;
        // 组装MAP集合
        for (ModelAnalyseInDto dto : storeDtos) {
            // 获取门店编码
            areaCode = dto.getStoreCode();
            temp = modelMap.get(areaCode);
            // 数据集合不存在,默认新建数据集合
            if (CollectionUtils.isEmpty(temp)) {
                temp = new ArrayList<ModelAnalyseInDto>();
            }
            temp.add(dto);
            // 按照对应的区域编码,保存到MAP中
            modelMap.put(areaCode, temp);
        }
        // 迭代区域编码, 按照月份组装对应区域12个月有效率数据
        Iterator<Entry<String, List<ModelAnalyseInDto>>> areaCodes = modelMap.entrySet().iterator();
        ModelAnalyseInDto firstModel;
        while (areaCodes.hasNext()) {
            temp = modelMap.get(areaCodes.next().getKey());
            // 默认取第一条数据,设置大区名称,分公司名称
            firstModel = temp.get(0);
            areaVo = new ModelValidInAreaVo();
            areaVo.setStoreCode(firstModel.getStoreCode());
            areaVo.setStoreName(firstModel.getStoreName());
            // 转换12个月有效率数据
            areaVo.setRates(convertModelValid(months, temp));
            list.add(areaVo);
        }
        return list;
    }

    /**
     * 创建临时样机销售排行CSV文件JOB
     * 
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    @Override
    public void createCommRankFileJob() {
        // 创建文件
        File file = CsvUtils.createCsvFile("model-sale-rank");
        Map<String, Object> queryMap = new HashMap<String, Object>();
        queryMap.put("saleMonth", DateUtils.getLastMonth());
        // 查询总记录数
        Integer total = dalClient.queryForObject("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_TOP_TOTAL", queryMap,
                Integer.class);
        // 没有记录时,返回
        if (null == total || total <= 0) {
            // 删除临时文件
            if (!file.delete()) {
                LOGGER.error(" createCommRankFileJob delete temp file error");
            }
            return;
        }
        int loop = (total % loopSize == 0) ? total / loopSize : (total / loopSize + 1);
        // 头信息
        Object[] header = new Object[] { "品类编码", "品类名称", "品牌编码", "品牌名称", "商品编码", "商品名称", "样机数量", "有效率", "销售量" };
        List<List<String>> csvFile;
        for (int i = 0; i < loop; i++) {
            // 查询分页数据
            csvFile = queryModelTop(i * loopSize, loopSize);
            // 记录不为空时,写文件
            if (CollectionUtils.isNotEmpty(csvFile)) {
                // 首次写头信息
                if (i == 0) {
                    CsvUtils.writeCsvFile(file.getAbsolutePath(), csvFile, header);
                } else {
                    CsvUtils.writeCsvFile(file.getAbsolutePath(), csvFile, null);
                }
            }
        }

        // 上传内部文件系统
        ImageServiceClient ifs = new ImageServiceClientImpl("ifs");
        InputStream in = null;
        try {
            in = new FileInputStream(file);
            // 上传上月文件
            ifs.onlyUpload("snsawp", "csv", "modelSaleTopRank" + DateUtils.getLastMonth(), null, "csv", in, "test123");
            // 删除上上月文件
            ifs.deleteFile("snsawp", "csv", "modelSaleTopRank" + DateUtils.getMonth(-2), null, "csv", "test123");
        } catch (ImageServiceException e) {
            LOGGER.error(" createCommRankFileJob ImageServiceException error", e);
        } catch (FileNotFoundException e) {
            LOGGER.error(" createCommRankFileJob FileNotFoundException error", e);
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (Exception e) {
                    LOGGER.error(" createCommRankFileJob close InputStream error", e);
                }
                try {
                    // 删除文件
                    if (!file.delete()) {
                        LOGGER.error(" createCommRankFileJob delete temp file error");
                    }
                } catch (Exception e) {
                    LOGGER.error(" createCommRankFileJob delete temp file error", e);
                }
            }
        }
    }

    /**
     * 分批查询样机销售排行
     * 
     * @param currIndex
     * @param size
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    private List<List<String>> queryModelTop(int currIndex, int size) {
        LOGGER.info("queryModelTop enter,currIndex={},size={}", currIndex, size);
        List<List<String>> csvFile = new ArrayList<List<String>>();
        Map<String, Object> queryMap = new HashMap<String, Object>();
        queryMap.put("currIndex", currIndex);
        queryMap.put("size", size);
        // 取上月的排行
        queryMap.put("saleMonth", DateUtils.getLastMonth());
        // 查询库数据
        List<ModelSaleTopInDto> modelTops = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_CONTRIBUTION_TOP",
                queryMap, ModelSaleTopInDto.class);
        if (CollectionUtils.isNotEmpty(modelTops)) {
            List<String> rows;
            for (ModelSaleTopInDto dto : modelTops) {
                rows = new ArrayList<String>();
                rows.add(dto.getCateCode());
                rows.add(dto.getCateName());
                rows.add(dto.getBrandCode());
                rows.add(dto.getBrandName());
                rows.add(dto.getCommCode());
                rows.add(dto.getCommName());
                rows.add(String.valueOf(dto.getModelTotal()));
                rows.add(DJStringUtils.calculateRateString(dto.getValidNum().toString(), dto.getModelCnt().toString()));
                rows.add(String.valueOf(dto.getSaleNum()));
                csvFile.add(rows);
            }
        }
        LOGGER.info("queryModelTop exit,currIndex={},size={}", currIndex, size);
        return csvFile;
    }

    /**
     * 功能描述: 分公司用户查询分公司样机推荐商品<br>
     * 〈功能详细描述〉被推荐的商品为此分公司所在大区的热销
     * 
     * @param orgCode
     * @param cateCode
     * @return
     */
    @Override
    public List<ModelRecommendBaseVo> queryRecommendCompany(String orgCode, String cateCode) {

        // 查询条件为空直接返回空
        if (StringUtils.isBlank(orgCode) || StringUtils.isBlank(cateCode)) {
            return Collections.emptyList();
        }

        Map<String, Object> queryMap = new HashMap<String, Object>();
        queryMap.put("orgCode", orgCode);
        queryMap.put("cateCode", cateCode);

        List<ModelCompanyRecommendDto> result = dalClient.queryForList(
                "MODEL_ANALYSE_IN.QUERY_MODEL_COMPANY_RECOMMEND", queryMap, ModelCompanyRecommendDto.class);

        // 结果不为空时转换对象
        if (CollectionUtils.isNotEmpty(result)) {
            ModelRecommendBaseVo vo = null;
            List<ModelRecommendBaseVo> list = new ArrayList<ModelRecommendBaseVo>();
            for (ModelCompanyRecommendDto dto : result) {
                vo = new ModelRecommendBaseVo();
                vo.setCateCode(dto.getCateCode());
                vo.setCateName(dto.getCateName());
                vo.setBranchCode(dto.getBranchCode());
                vo.setBranchName(dto.getBranchName());
                vo.setCommCode(dto.getCommCode());
                vo.setCommName(dto.getCommName());
                vo.setSaleNum(dto.getSaleNum());
                list.add(vo);
            }
            return list;
        }
        return Collections.emptyList();
    }

    /**
     * 功能描述: 大区用户查询大区样机推荐商品<br>
     * 〈功能详细描述〉被推荐的商品为此全国级别的热销
     * 
     * @param disCode
     * @param cateCode
     * @return
     */
    @Override
    public List<ModelRecommendBaseVo> queryRecommendArea(String disCode, String cateCode) {

        // 查询条件为空直接返回空
        if (StringUtils.isBlank(disCode) || StringUtils.isBlank(cateCode)) {
            return Collections.emptyList();
        }

        Map<String, Object> queryMap = new HashMap<String, Object>();
        queryMap.put("disCode", disCode);
        queryMap.put("cateCode", cateCode);

        List<ModelAreaRecommendDto> result = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_AREA_RECOMMEND",
                queryMap, ModelAreaRecommendDto.class);

        // 结果不为空时转换对象
        if (CollectionUtils.isNotEmpty(result)) {
            ModelRecommendBaseVo vo = null;
            List<ModelRecommendBaseVo> list = new ArrayList<ModelRecommendBaseVo>();
            for (ModelAreaRecommendDto dto : result) {
                vo = new ModelRecommendBaseVo();
                vo.setCateCode(dto.getCateCode());
                vo.setCateName(dto.getCateName());
                vo.setBranchCode(dto.getBranchCode());
                vo.setBranchName(dto.getBranchName());
                vo.setCommCode(dto.getCommCode());
                vo.setCommName(dto.getCommName());
                vo.setSaleNum(dto.getSaleNum());
                list.add(vo);
            }
            return list;
        }
        return Collections.emptyList();
    }

    @Override
    public List<ModelRecommendBaseVo> queryModelTopTwenty(String disCode, String orgCode, String cateCode, String flag) {

        if ((StringUtils.isBlank(cateCode) || StringUtils.isBlank(disCode) || StringUtils.isBlank(orgCode))
                && StringUtils.isBlank(flag)) {
            return Collections.emptyList();
        }
        Map<String, Object> queryMap = new HashMap<String, Object>();
        queryMap.put("flag", flag);
        if (StringUtils.isNotBlank(disCode)) {
            queryMap.put("disCode", disCode);
        }
        if (StringUtils.isNotBlank(orgCode)) {
            queryMap.put("orgCode", orgCode);
        }
        queryMap.put("cateCode", cateCode);
        // 查询门店TOP排行
        List<ModelRecommendBaseVo> result = dalClient.queryForList("MODEL_ANALYSE_IN.QUERY_MODEL_TOP_TWENTY", queryMap,
                ModelRecommendBaseVo.class);
        LOGGER.debug("model in queryModelTopTwenty resp={},disCode={},orgCode={},cateCode={},flag={}", result, disCode,
                orgCode, cateCode, flag);
        return result;
    }

}
